﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace CSharp.Infrastructure
{
    /// <summary>
    /// 七牛云短信提醒
    /// </summary>
    public class QiniuSmsHelper
    {
        private List<UserSessionInfo> dataList = new List<UserSessionInfo>();
        private static Random random = new Random((int)DateTime.Now.ToFileTimeUtc());

        private string ak = string.Empty;
        private string sk = string.Empty;

        public QiniuSmsHelper(string ak, string sk)
        {
            this.ak = ak;
            this.sk = sk;
        }

        /// <summary>
        /// 发送提示短信
        /// </summary>
        /// <param name="phone"></param>
        /// <param name="code"></param>
        /// <returns>
        /// 返回默认结果
        /// </returns>
        public string SendCommonMsg(string phone, string code = "")
        {
            try
            {
                string postData = $@"{{""mobiles"":[""{phone}""],""template_id"":""1535144840386330624"",""parameters"":{{""code"":""{code}""}}}}";
                string authorization = getAuthorization(postData);
                string url = "https://sms.qiniuapi.com/v1/message";

                Dictionary<string, string> header = new Dictionary<string, string>();
                header.Add("Authorization", authorization);

                string content = HttpClientHelper.PostResponse_JSON(url, postData, header);

                Console.WriteLine("PtCAICTHelper_Qiniu SendWarningSms " + content);
                if (!content.Contains("\"job_id\""))
                {
                    return "";
                }

                return content;
            }
            catch (Exception e)
            {
                Logs.WriteLog(LogType.Error, "SendWarningSms e " + e.ToString());
                return "";
            }
        }

        /// <summary>
        /// 发送验证码
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="phone"></param>
        /// <returns></returns>
        public string SendLoginSms(string template_id, string sessionId, string phone, string code = "")
        {
            try
            {
                if (string.IsNullOrEmpty(code))
                {
                    code = random.Next(1, 1000000).ToString().PadLeft(6, '0');
                }

                string postData = string.Format($@"{{""mobiles"":[""{phone}""],""template_id"":""{template_id}"",""parameters"":{{""code"":""{code}""}}}}");
                string authorization = getAuthorization(postData);
                string url = "https://sms.qiniuapi.com/v1/message";

                Dictionary<string, string> header = new Dictionary<string, string>();
                header.Add("Authorization", authorization);
                string content = HttpClientHelper.PostResponse_JSON(url, postData, header);

                Console.WriteLine("PtCAICTHelper_Qiniu GetPhoneSms " + content);
                if (!content.Contains("\"job_id\""))
                {
                    return "";
                }

                lock (dataList)
                {
                    dataList.RemoveAll(a => a.updateTime.AddMinutes(10) < DateTime.Now);
                    var item = dataList.Find(p => p.sessionId == sessionId);
                    if (item == null)
                    {
                        item = new UserSessionInfo();
                        item.sessionId = sessionId;
                        item.is_login = false;
                        item.phone = phone;
                        item.code = code;
                        item.error_times = 0;
                        item.updateTime = DateTime.Now;
                        dataList.Add(item);
                    }
                    else
                    {
                        item.is_login = false;
                        item.phone = phone;
                        item.code = code;
                        item.error_times = 0;
                        item.updateTime = DateTime.Now;
                    }
                }

                return code;
            }
            catch (Exception e)
            {
                Logs.WriteLog(LogType.Error, "GetPhoneSms e " + e.ToString());
                return "";
            }
        }

        /// <summary>
        /// 检查短信正确性
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool CheckSms(string sessionId, string code)
        {
            try
            {
                var item = QueryInfo(sessionId);
                if (item != null)
                {
                    if (item.error_times > 3)
                    {
                        return false;
                    }

                    if (code == item.code)
                    {
                        item.is_login = true;
                        return true;
                    }
                    else
                    {
                        item.error_times++;

                        // 失败次数+1.三次失败，就必须重新来短信了
                        return false;
                    }
                }

                return false;
            }
            catch (Exception e)
            {
                Logs.WriteLog(LogType.Error, "Login sessionId " + sessionId + " code " + code + " ex " + e.ToString());

                return false;
            }
        }

        private UserSessionInfo QueryInfo(string sessionId)
        {
            lock (dataList)
            {
                var item = dataList.Find(p => p.sessionId == sessionId);
                if (item != null)
                {
                    item.updateTime = DateTime.Now;
                }

                return item;
            }
        }

        private string getAuthorization(string json)
        {
            // Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
            StringBuilder content = new StringBuilder("POST /v1/message\n");
            content.Append("Host: sms.qiniuapi.com\n");
            content.Append("Content-Type: application/json\n\n");
            content.Append(json);

            // + -> -  / -> _  安全的base64
            return "Qiniu " + ak + ":" + Convert.ToBase64String(hash_hmac(content.ToString(), sk)).Replace('+', '-').Replace('/', '_'); ;
        }

        private byte[] hash_hmac(string signatureString, string secretKey)
        {
            var enc = Encoding.UTF8;
            HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(secretKey));
            hmac.Initialize();

            byte[] buffer = enc.GetBytes(signatureString);

            return hmac.ComputeHash(buffer);
        }
    }

    /// <summary>
    /// 短信身份
    /// </summary>
    public class UserSessionInfo
    {
        public string sessionId { get; set; }

        public string phone { get; set; }

        public DateTime updateTime { get; set; }

        public string code { get; set; }

        public bool is_login { get; set; }

        public int error_times { get; set; }
    }
}